package net.cloudcodex.client.storyboard.player.presenter;

import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

import net.cloudcodex.client.storyboard.player.PlayerBoardEventBus;
import net.cloudcodex.client.storyboard.player.view.PlayerBoardView;
import net.cloudcodex.client.storyboard.player.view.PlayerBoardView.Message;
import net.cloudcodex.client.storyboard.player.view.PlayerBoardViewImpl;
import net.cloudcodex.client.util.rpc.IgnoreCallback;
import net.cloudcodex.client.util.rpc.SuccessCallback;
import net.cloudcodex.shared.dto.Result;
import net.cloudcodex.shared.dto.msg.SceneDTO;
import net.cloudcodex.shared.rpc.CampaignRPCAsync;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.inject.Inject;
import com.mvp4g.client.annotation.Presenter;
import com.mvp4g.client.presenter.BasePresenter;

/**
 * 
 * 
 * @author ADaroussin
 */
@Presenter(view = PlayerBoardViewImpl.class, multiple = true)
public class PlayerBoardPresenter extends BasePresenter<PlayerBoardView, PlayerBoardEventBus> {
	private final Message message;
	private final CampaignRPCAsync service;

	private final SortedMap<Long, ScenePresenter> scenePresenters = new TreeMap<Long, ScenePresenter>();

	private PlayerCommandPresenter commandPresenter;

	private long campaignId;
	private long characterId;
	private Long activeSceneId;

	@Inject
	public PlayerBoardPresenter(Message message, CampaignRPCAsync service) {
		this.message = message;
		this.service = service;
	}

	@Override
	public void bind() {
		super.bind();
		this.view.getNewSceneButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				service.justForTestsDoSomethingRandomly(campaignId, characterId, 1,
						new IgnoreCallback<Result<Boolean>>());
			}
		});
		this.view.getTalkButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				service.justForTestsDoSomethingRandomly(campaignId, characterId, 2,
						new IgnoreCallback<Result<Boolean>>());
			}
		});
		this.view.getOffButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				service.justForTestsDoSomethingRandomly(campaignId, characterId, 3,
						new IgnoreCallback<Result<Boolean>>());
			}
		});
		this.view.getRollButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				service.justForTestsDoSomethingRandomly(campaignId, characterId, 5,
						new IgnoreCallback<Result<Boolean>>());
			}
		});
		this.view.getDeleteButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				service.justForTestsDoSomethingRandomly(campaignId, characterId, 4,
						new IgnoreCallback<Result<Boolean>>());
			}
		});
		this.view.getReindexButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				service.justForTestsDoSomethingRandomly(campaignId, characterId, 6,
						new IgnoreCallback<Result<Boolean>>());
			}
		});
	}

	public void initPlayerBoard(long campaignId, long characterId) {
		this.campaignId = campaignId;
		this.characterId = characterId;
		this.eventBus.registerToScene(campaignId, characterId, new SuccessCallback<List<SceneDTO>>() {
			@Override
			public void onSuccess(List<SceneDTO> scenes) {
				mergeScenes(scenes);
			}
		});

		// Init player commands
		this.commandPresenter = eventBus.addHandler(PlayerCommandPresenter.class);
		this.commandPresenter.setCampaignId(campaignId);
		this.commandPresenter.setCharacterId(characterId);
		this.view.setCommand(this.commandPresenter.getView());
	}

	public long getCampaignId() {
		return this.campaignId;
	}
	
	public long getCharacterId() {
		return this.characterId;
	}
	
	private void mergeScenes(List<SceneDTO> scenes) {
		for (SceneDTO scene : scenes) {
			final Long sceneId = scene.getId();
			ScenePresenter scenePresenter = this.scenePresenters.get(sceneId);
			if (scenePresenter == null) {
				// Init new scene presenter
				scenePresenter = this.eventBus.addHandler(ScenePresenter.class);
				scenePresenter.setParent(this);
				this.scenePresenters.put(sceneId, scenePresenter);
				this.view.addScene(scenePresenter.getView());
			}
			final int sceneIdComparison = activeSceneId == null ? 1 : sceneId.compareTo(activeSceneId);
			if (sceneIdComparison >= 0) {
				// Active scene is updated
				this.commandPresenter.setSceneTimestamp(scene.getTimestamp());
				if (sceneIdComparison > 0) {
					// New active scene
					activeSceneId = sceneId;
					this.commandPresenter.setSceneId(sceneId);
				}
			}
			scenePresenter.mergeScene(scene);
		}
	}
}
